﻿package util 
{
	import events.LoaderEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	
	/**
	 * Class, which loads xml and returns data
	 * @author kasoi
	 */
	public class XMLLoader extends EventDispatcher
	{
		[Event(name = "ioError", type = "flash.events.IOErrorEvent")]
		[Event(name = "loadComplete", type = "events.LoaderEvent")]
		[Event(name = "securityError", type = "flash.events.SecurityErrorEvent")]
		
		////////////////////////////////////////////////////////////////////
		// Public properties
		////////////////////////////////////////////////////////////////////
		
		public function get data() : XML
		{
			return this._data;
		}
		
		////////////////////////////////////////////////////////////////////
		// Private methods
		////////////////////////////////////////////////////////////////////
		
		private var loader: URLLoader;
		
		private var isLoadToFunction: Boolean = false;
		
		private var method: Function;
		
		private var _data: XML;
		
		private var checkPolicyFile: Boolean = false;
		
		////////////////////////////////////////////////////////////////////
		// Public methods
		////////////////////////////////////////////////////////////////////
		
		public function XMLLoader() : void 
		{
		}
		
		/*
		 * @param url - path to XML
		 * @param random - adds random value to url [?rand=999] for non-caching
		 */
		public function load(url: String, random: Boolean = false) : void 
		{
			var rnd: String = '';
			var d: Date = new Date();
			if (random) 
			{
				var rndSym: String = '?';
				if (url.split('?').length > 1) rndSym = '&';
				rnd = rndSym + 'rnd_value=' + d.fullYear + '' + d.month + '' 
				+ d.day + '' + d.hours + '' + d.minutes + '' + d.seconds + '' 
				+ d.milliseconds + '_' + Math.random();
			}
			this.isLoadToFunction = false;
			this.checkPolicyFile = checkPolicyFile;
			var req: URLRequest = new URLRequest(url + rnd);
			this.loader = new URLLoader(req);
			
			this.loader.addEventListener(Event.COMPLETE, this.loader_onLoad);
			this.loader.addEventListener(ProgressEvent.PROGRESS, this.loader_onProgress);
			this.loader.addEventListener(IOErrorEvent.IO_ERROR, this.loader_onIoError);
			this.loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, 
				this.loader_onSecurityError);
		}
		
		/*
		 * @param url - path to XML
		 * @param method - method which calls while xml complete loading. [ Function(data: XML) ]
		 * @param random - adds random value to url [?rand=999] for non-caching
		 */
		public function loadToFunction(url: String, method: Function,
			random: Boolean = false) : void 
		{
			this.load(url, random);
			this.isLoadToFunction = true;
			this.method = method;
		}
		
		public function clean() : void 
		{
			if (!this.loader) return;
			this.loader.removeEventListener(Event.COMPLETE, this.loader_onLoad);
			this.loader.removeEventListener(ProgressEvent.PROGRESS, this.loader_onProgress);
			this.loader.removeEventListener(IOErrorEvent.IO_ERROR, this.loader_onIoError);
		}
		
		////////////////////////////////////////////////////////////////////
		// Listeners
		////////////////////////////////////////////////////////////////////
		
		private function loader_onLoad(e: Event) : void 
		{
			this._data = new XML(this.loader.data);
			
			this.loader.removeEventListener(Event.COMPLETE, this.loader_onLoad);
			this.loader.removeEventListener(ProgressEvent.PROGRESS, this.loader_onProgress);
			
			if(this.isLoadToFunction) this.method(this._data);
			
			this.dispatchEvent(new LoaderEvent(LoaderEvent.LOAD_COMPLETE)); // TODO
		}
		
		private function loader_onProgress(e: ProgressEvent) : void 
		{
			var l: Number = this.loader.bytesLoaded;
			var t: Number = this.loader.bytesTotal;
			var p: Number = l / t;
			this.dispatchEvent(new LoaderEvent(LoaderEvent.PROGRESS, p));
		}
		
		private function loader_onIoError(e: Event) : void 
		{
			this.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
		}
		
		private function loader_onSecurityError(e: SecurityErrorEvent) : void 
		{
			this.dispatchEvent(e);
		}
	}
	
}